//////////////////////////////////////////////////////////////////////////
//
// This file is a part of UKROP project.
// Copyright (c) Vladimir Gumenuk, 2008-2014.
//
// PROJECT:         Xort compiler
// FILE:            WinFile.cpp - native object support (example)
// AUTHOR:          Vladimir Gumenuk
// DATE:            3-Sep-2014
//
//////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WinFile.h"

CWinFile::CWinFile()
{
    m_hFile = NULL;
    m_dwRefCount = 0;
}

CWinFile::~CWinFile()
{

}

int CWinFile::Invoke( lpcstr lpszName, XNIVariantArray *pArgs, XNIVariant& vResultOut )
{
    if( !lpszName )
        return FALSE;

    int iRet = FALSE;

    if( strcmp( lpszName, "Open" ) == 0 )
    {
        if( !pArgs || pArgs->GetCount() != 2 )
            return iRet;

        XNIVariant vName, vMode;
        iRet = pArgs->GetValue( 0, vName );
        if( iRet != XOK )
            return iRet;

        if( vName.bType != xni_str || !vName._str )
            return FALSE;

        iRet = pArgs->GetValue( 1, vMode );
        if( iRet != XOK )
            return iRet;

        if( vMode.bType != xni_str || !vMode._str )
            return FALSE;

        iRet = Open( vName._str, vMode._str );

        vResultOut.bType = xni_s4;
        vResultOut._s4 = iRet; // this is the result of actual method invocation

        iRet = TRUE; // result of Invoke
    }
    else if( strcmp( lpszName, "Close" ) == 0 )
    {
        Close();
        vResultOut.bType = xni_s4;
        vResultOut._s4 = 1;
        iRet = TRUE;
    }
    else if( strcmp( lpszName, "Length" ) == 0 )
    {
        vResultOut._u4 = Length();
        vResultOut.bType = xni_u4;
        iRet = TRUE;
    }
    else if( strcmp( lpszName, "Name" ) == 0 )
    {
        dword dwSize = m_strFileName.length() + 1;

        vResultOut._str = new char [ dwSize ];
        if( !vResultOut._str )
            return FALSE;

        strcpy( vResultOut._str, Name() );
        vResultOut.bType = xni_str;
        vResultOut.dwSize = dwSize;
        iRet = TRUE;
    }
    else if( strcmp( lpszName, "isOpened" ) == 0 )
    {
        vResultOut.bType = xni_s4;
        vResultOut._s4 = isOpened();
        iRet = TRUE;
    }
    else if( strcmp( lpszName, "Read" ) == 0 )
    {
        if( !pArgs || pArgs->GetCount() != 2 )
            return iRet;

        XNIVariant vBuf, vSize;

        iRet = pArgs->GetValue( 0, vBuf );
        if( iRet != XOK )
            return iRet;

        if( vBuf.bType != xni_bin || !vBuf._bin )
            return FALSE;

        iRet = pArgs->GetValue( 1, vSize );
        if( iRet != XOK )
            return iRet;

        if( vSize.bType != xni_u4 || !vSize._u4 )
            return FALSE;

        vResultOut._u4 = Read( vBuf._bin, vSize._u4 );
        vResultOut.bType = xni_u4;
        iRet = TRUE;
    }
    else if( strcmp( lpszName, "Write" ) == 0 )
    {
        if( !pArgs || pArgs->GetCount() != 2 )
            return iRet;

        XNIVariant vBuf, vSize;

        iRet = pArgs->GetValue( 0, vBuf );
        if( iRet != XOK )
            return iRet;

        if( vBuf.bType != xni_bin || !vBuf._bin )
            return FALSE;

        iRet = pArgs->GetValue( 1, vSize );
        if( iRet != XOK )
            return iRet;

        if( vSize.bType != xni_u4 || !vSize._u4 )
            return FALSE;

        vResultOut._u4 = Write( vBuf._bin, vSize._u4 );
        vResultOut.bType = xni_u4;
        iRet = TRUE;
    } 
    else if( strcmp( lpszName, "SaveVector3D" ) == 0 )
    {
        if( !pArgs || pArgs->GetCount() != 1 )
            return iRet;

        XNIVariant vVec;
        iRet = pArgs->GetValue( 0, vVec );
        if( iRet != XOK )
            return iRet;

        if( vVec.bType != xni_bin || vVec.dwSize != sizeof(Vector3D) || !vVec._bin )
            return FALSE;

        iRet = SaveVector3D( (Vector3D*)vVec._bin );
        vResultOut.bType = xni_s4;
        vResultOut._s4 = iRet;
    }

    return iRet;
}

//////////////////////////////////////////////////////////////////////////
// implementation
int CWinFile::Open( LPCSTR csName, LPCSTR csMode )
{
    if( m_hFile )
        return FALSE;

    m_hFile = fopen( csName, csMode );
    if( !m_hFile )
    {
        return FALSE;
    } else
        m_strFileName = csName;

    return TRUE;
}

int CWinFile::Close()
{
    if( m_hFile )
    {
        fclose( m_hFile );
        m_hFile = 0;

        m_strFileName.empty();

        return TRUE;
    }

    return FALSE;
}

DWORD CWinFile::Length()
{
    if( !m_hFile )
        return 0;

    DWORD dwCurPos = ftell( m_hFile );
    fseek( m_hFile, 0, SEEK_END );
    DWORD dwLength = ftell( m_hFile );
    fseek( m_hFile, dwCurPos, SEEK_SET );
    return dwLength;
}

LPCSTR CWinFile::Name()
{
    return m_strFileName.c_str();
}

int CWinFile::isOpened()
{
    return m_hFile != 0 ? TRUE : FALSE;
}

DWORD CWinFile::Read(LPBYTE buf, DWORD dwCount)
{
    if( !m_hFile )
        return 0;

    DWORD dwRead = fread( buf, 1, dwCount, m_hFile );
    
    return dwRead;
}

DWORD CWinFile::Write( const LPBYTE buf, DWORD dwCount )
{
    if( !m_hFile || dwCount == 0 )
        return 0;

    DWORD dwWritten = fwrite( buf, 1, dwCount, m_hFile );
    return dwWritten;
}

int CWinFile::SaveVector3D( Vector3D *lpVec )
{
    if( !m_hFile || !lpVec )
        return 0;

    int iWritten = fwrite( lpVec, 1, sizeof(Vector3D), m_hFile );
    return iWritten;
}
